package com.tang.client;

import com.tang.domain.Constants;
import com.tang.domain.FileSliceData;
import com.tang.domain.FileSliceInstruct;
import com.tang.domain.FileTransferProtocol;
import com.tang.util.FileUtil;
import com.tang.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;

import java.time.LocalDateTime;

/**
 * 自定义消息处理类
 *
 * @author fulin.tang
 * @version V3.0
 * @since 2022/3/9 14:28
 */
@Slf4j
public class MyClientHandler extends ChannelInboundHandlerAdapter {

    // 链接事件
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("有新的连接：CHANNEL_ID:{}, ADDRESS:{}", ctx.channel().id(), ctx.channel().localAddress());
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("断开链接：{}", ctx.channel().localAddress());
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        // 验证是否是我们定义的文件
        if (!(msg instanceof FileTransferProtocol)) return;

        FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;

        // 如果是文件传输指令1
        if (fileTransferProtocol.getTransferType() == 1) {
            // 将数据转换成分片指令
            FileSliceInstruct fileBurstInstruct = (FileSliceInstruct) fileTransferProtocol.getTransferObj();
            // 是否是已经完成的指令
            if (Constants.FileStatus.COMPLETE == fileBurstInstruct.getStatus()) {
                ctx.flush();
                ctx.close();
                System.exit(-1);
                return;
            }
            // 如果不是已完成的指令，那么就接着读文件
            FileSliceData fileBurstData = FileUtil.readFile(fileBurstInstruct.getClientFileUrl(), fileBurstInstruct.getReadPosition()); // 文件分片数据
            FileTransferProtocol data = MsgUtil.buildTransferData(fileBurstData);
            ctx.writeAndFlush(data);
            log.info("{} 客户端传输的文件信息。FILE: {} SIZE: {}", LocalDateTime.now(), fileBurstData.getFileName(), fileBurstData.getEndPos() - fileBurstData.getBeginPos());
        }

        /*
         * 模拟传输过程中断场景
         */
        /*log.info("{} 客户端传输文件信息[主动断开连接，模拟断点续传]", LocalDateTime.now());
        ctx.flush();
        ctx.close();
        System.exit(-1);*/
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
        log.info("异常信息：{}", cause.getMessage());
    }
}
